; opcodes.scm - Sassy's opcode parsers and code generators
; Copyright (C) 2005 Jonathan Kraut

; This library is free software; you can redistribute it and/or
; modify it under the terms of the GNU Lesser General Public
; License as published by the Free Software Foundation; either
; version 2.1 of the License, or (at your option) any later version.

; This library is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
; Lesser General Public License for more details.

; You should have received a copy of the GNU Lesser General Public
; License along with this library; if not, write to the Free Software
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

; Contact:
; Jonathan Kraut
; 4130 43 ST #C2
; Sunnyside, NY 11104
; jak76@columbia.edu

; see file COPYING in the top of Sassy's distribution directory


; module opcodes
; import operands numbers api text-block push-stacks
; import-syntax meta-lambda
; export opcode? emit-direct emit-direct2

 
; At first the shared vars w l t r were a quick fix to get around some
; scoping issues but lookie-lookie: this speeds things up from 4 to 10
; times (in mzscheme, at least) so hooray local-global vars!!!
; Anywho, these are here because handle-text-symbol and
; handle-rel-symbol need them.  Otherwise they would have to be passed
; through the opcode parsers and through the sub-emitters until, for
; instance handle-imm could pass them to handle-text-symbol.

(define emit-direct  #f)
(define emit-direct2 #f)
(define opcode?      #f)

(let ((w #f)  ;win
      (l #f)  ;lose
      (t #f)  ;text-block
      (r #f)  ;output
      (addr-flag #f) ;flag to emit address-size prefix
      (seg-flag #f))  ;flag to emit segment override prefix

  ; only used for internally generated instructions, no error check
  (define (%emit-direct instr win lose textb outp)
    (set! w win)
    (set! l lose)
    (set! t textb)
    (set! r outp)
    (set! addr-flag #f)
    (set! seg-flag #f)
    ((hash-table-ref the-opcodes (car instr)) (cdr instr))
    (push-stack-size (t-text t)))

  ; this is the used for instructions the user wrote
  (define (%emit-direct2 name opcode args win lose textb outp)
    (set! w win)
    (set! l lose)
    (set! t textb)
    (set! r outp)
    (set! addr-flag #f)
    (set! seg-flag #f)
    (or (and (opcode args)
	     (push-stack-size (t-text t)))
	(error "sassy: bad operands" (cons name args))))

  (define (outc itm) (push-stack-push (t-text t) itm))

  (define (outc-maybe-quoted-list itm)
    (push-stack-push (t-text t) (if (pair? itm) (apply list itm) itm)))

  (define (check-size sizer)
    (when addr-flag (outc #x67))
    (when (and (not (= sizer 1))
	       (not (= sizer (/ (sassy-bits r) 8))))
	  (outc #x66))
    (when seg-flag (outc seg-flag)))

  (define (handle-r/r eff-add reg) (outc (+ 192 eff-add (* 8 reg))))

  (define (handle-imm sizer imm-value)
    (cond ((number? imm-value) (outc (number->byte-list imm-value sizer)))
	  ((symbol? imm-value) (handle-text-symbol 'abs imm-value 0 sizer))
	  (else (apply handle-text-symbol (cdr imm-value)))))

  (define (handle-text-symbol type target value . maybe-size)
    (define current-byte-size (if (not (null? maybe-size))
				  (car maybe-size)
				  (/ (sassy-bits r) 8)))
    (define k? #f)
    (define (setup x)
      (set! k? #t)
      (if (pair? x)
	  (if (opcode? (car x))
	      (error "sassy: bad context for instruction as continuation" x)
	      (begin (set! type   (cadr x))
		     (set! target (caddr x))
		     (set! value  (cadddr x))))
	  (set! target x)))
    (case target
      (($win)  (setup w))
      (($lose) (setup l))
      (($eip)  (setup (push-stack-size (t-text t)))))
    (let* ((pnt   (push-stack-push->patcher
		   (t-text t)
		   (number->byte-list value current-byte-size)))
	   (offs  (push-stack-size (t-text t)))
	   (t-val (cond ((sassy-symbol-exists-env? r target) =>
			 (lambda (x) (sassy-symbol-offset x)))
			(else target)))
	   (a-reloc (make-sassy-reloc (get-reloc-target target r)
				      'text offs type #f value
				      current-byte-size))
	   (patcher (lambda (new)
		      (pnt (number->byte-list new current-byte-size))
		      (sassy-reloc-value-set! a-reloc new))))
      (sassy-reloc-patcher-set! a-reloc patcher)
      (push-t-reloc! t a-reloc)
      (if (not k?)
	  (if (number? t-val)
	      (patcher (+ t-val value))
	      (sassy-symbol-set!
	       r target `(unres ,(lambda (n) (patcher (+ n value))))))
	  (push-t-res!
	   t (cons t-val (lambda (n) (patcher (+ n value))))))))

  (define (handle-rel-symbol sizer type target value)
    (define k? #f)
    (define (setup x)
      (set! k? #t)
      (if (pair? x)
	  (if (opcode? (car x))
	      (error "sassy: bad context for instruction as continuation" x)
	      (begin (set! type (cadr x))
		     (set! target (caddr x))
		     (set! value (cadddr x))))
	  (set! target x)))
    (case target
      (($win)  (setup w))
      (($lose) (setup l))
      (($eip)  (setup (push-stack-size (t-text t)))))
    (let* ((offs  (push-stack-size (t-text t)))
	   (pnt   (push-stack-push->patcher (t-text t)
					    (number->byte-list value sizer)))
	   (t-val (cond ((sassy-symbol-exists-env? r target)
			 => sassy-symbol-offset)
			(else target)))
	   (a-reloc (make-sassy-reloc
		     (get-reloc-target target r)
		     'text (+ offs sizer) type #f value sizer))
	   (patcher (lambda (new)
		      (if (not ((case sizer
				 ((1) s-byte)
				 ((2) s-word)
				 ((4) s-dword))
				new))
			  (error "sassy: out of range" (+ new sizer 1))
			  (begin (pnt (number->byte-list new sizer))
				 (sassy-reloc-value-set! a-reloc new))))))
      (when (= 4 sizer)
	    (sassy-reloc-patcher-set! a-reloc patcher)
	    (push-t-reloc! t a-reloc))
      (when (and (= 2 sizer) (= 16 (sassy-bits r)))
	    (sassy-reloc-patcher-set! a-reloc patcher)
	    (push-t-reloc! t a-reloc))
      (if (not k?)
	  (if (and (number? t-val) (eqv? 'rel type))
	      (push-t-res!
	       t (cons offs (lambda (n) (patcher (- t-val n)))))
	      (push-t-unres!
	       t (list target offs (lambda (from)
				     (lambda (to)
				       (patcher (- to from))))
		       (cond ((sassy-symbol-exists-env? r target) =>
			      sassy-symbol-scope)
			     (else #f)))))
	  (patcher (- offs t-val)))))


  (define (handle-mem ref reg)
    (letrec
	((bad-mem (lambda () (error "sassy: bad memory-ref" (cons '& ref))))
	 (base   #f)  (ix     #f)  (sk     0)  (mod    0)  (r/m    #f)
	 (symb #f)  (disp   #f) (type 'abs)
	 (comp-mod
	  (lambda () (if (or disp symb)
			 (cond ((and (u/s-byte disp) (not symb)) (set! mod 64))
			       ((or (u/s-dword disp) symb) (set! mod 128))
			       (else (bad-mem))))))
	 (fix-disp
	  (lambda () (if (or disp symb)
			 (cond ((and (u/s-byte disp) (not symb))
				(set! disp `(byte ,disp)))
			       ((or (u/s-dword disp) symb)
				(set! disp (if disp `(dword ,disp) '(dword 0))))
			       (else (bad-mem))))))
	 (skale (meta-lambda (or ,@1
				 (and ,@2 (begin (set! sk 64)))
				 (and ,@4 (begin (set! sk 128)))
				 (and ,@8 (begin (set! sk 192))))))
	 (mem-i
	  (meta-lambda
	   (or
	    (and ,@r32 (lambda (x) (cond ((not r/m) (set! r/m x))
					 ((not ix) (if (not (= x 4))
						       (set! ix (* 8 x))
						       (begin (set! ix
								    (* 8 r/m))
							      (set! r/m 4))))
					 (else (bad-mem)))))
	    (and ,@symbol (lambda (x)
			    (if (not symb)
				(if (symbol? x)
				    (set! symb x)
				    (begin (set! type (cadr x))
					   (set! symb (caddr x))
					   (if (not disp)
					       (set! disp (cadddr x))
					       (set! disp (+ disp
							     (cadddr x))))))
				(bad-mem))))
	    (and ,@integer? (lambda (x) (if (not disp)
					    (set! disp x)
					    (set! disp (+ x disp)))))
	    (and '* (or (and skale r32-not-esp (lambda (x y)
						 (set! ix (* 8 y))))
			(and r32-not-esp skale (lambda (x y)
						 (set! ix (* 8 x))))))
	    (else (lambda (x) (bad-mem)))))))
      (or (and (case (car ref)
		 ((cs) (set! seg-flag #x2e))
		 ((ss) (set! seg-flag #x36))
		 ((ds) (set! seg-flag #x3e))
		 ((es) (set! seg-flag #x26))
		 ((fs) (set! seg-flag #x64))
		 ((gs) (set! seg-flag #x65))
		 (else #f))
	       (for-each mem-i (cadr ref)))
	  (for-each mem-i ref))
;ok...here we go...
      (cond ((and (not r/m) (not ix))
	     (if (and (not symb) (not (u/s-dword disp)))
		 (bad-mem)
		 (begin (set! disp (if disp `(dword ,disp) '(dword 0)))
			(set! r/m 5))))
	    (r/m (if (and (= r/m 5) (not disp) (not symb))
		     (begin (set! mod 64)
			    (set! disp '(byte 0))
			    (if ix
				(begin (set! base r/m)
				       (set! r/m 4))
				(set! base r/m)))
		     (begin (comp-mod)
			    (fix-disp)
			    (cond ((and (= r/m 4) (not ix))
				   (set! ix 32)
				   (set! base r/m))
				  (ix (set! base r/m)
				      (set! r/m 4))))))
	    ((or (= sk 128) (= sk 192))
	     (if (or symb (and disp (u/s-dword disp)))
		 (set! disp (if disp `(dword ,disp) '(dword 0)))
		 (set! disp `(dword 0)))
	     (set! r/m 4)
	     (set! base 5))
	    (else (if (and (not disp)
			   (not symb)
			   (= ix 40))
		      (set! disp 0))
		  (comp-mod)
		  (if (zero? sk)
		      (begin (set! r/m (/ ix 8))
			     (set! ix #f))
		      (begin (set! r/m 4)
			     (set! base (/ ix 8))
			     (set! sk 0)))
		  (fix-disp)))
;whew!
      (when symb
	    (handle-text-symbol type symb (or (and disp (cadr disp)) 0) 4))
      (when (and disp (not symb))
	    (outc (number->byte-list (cadr disp) (case (car disp)
						   ((byte) 1)
						   ((dword) 4)))))
      (when (= 16 (sassy-bits r))
	    (set! addr-flag #t))
      (when ix (outc (+ sk ix base)))
      (outc (+ mod r/m (* 8 reg)))))

  (define (%opcode? x) (hash-table-ref the-opcodes x (lambda () #f)))

  (define the-opcodes
    (let ((rep-able
	   (lambda (x)
	     (and (pair? x)
		  (member (car x) '(insb insw insd outsb outsw outsd movsb
					 movsw movsd lodsb lodsw lodsd stosb
					 stosw stosd))
		  (null? (cdr x)) ;check for null due to ambiguity of movsd
		  x)))
	  (rep-e-able
	   (lambda (x)
	     (and (pair? x)
		  (member (car x) '(cmpsb cmpsw cmpsd scasb scasw scasd))
		  (null? (cdr x)) ;check for null due to ambiguity of cmpsd
		  x)))
	  (lock-able
	   (lambda (x)
	     (and (pair? x)
		  (member (car x) '(add adc and btc btr bts cmpxchg cmpxchg8b
					dec inc neg not or sbb sub xor xadd
					xchg))
		  (mem-any (cadr x))
		  x)))
	  (branch-predict-able
	   (lambda (x)
	     (and (pair? x)
		  (member (car x) '(jo jno jb jc jnae jnb jnc jae je jz jne
				       jnz jbe jna ja jnbe js jns jp jpe jnp
				       jpo jl jnge jge jnl jle jng jnle jg))
		  x))))
      (letrec
	  ((just-c     (lambda (sizer opcode)
			 (outc-maybe-quoted-list opcode)
			 (check-size sizer)))
	   (just-i     (lambda (sizer opcode imm-value . prefix?)
			 (if (null? prefix?)
			     (begin (handle-imm sizer imm-value)
				    (just-c sizer opcode))
			     (begin (handle-imm sizer imm-value)
				    (outc-maybe-quoted-list opcode)))))
	   (just-i8    (lambda (sizer opcode imm-value)
			 (handle-imm 1 imm-value)
			 (just-c sizer opcode)))
	   (just-i32   (lambda (sizer opcode imm-value) ; only used by mov mi
			 (if (= 16 (sassy-bits r))
			     (set! addr-flag #t))
			 (handle-imm 4 imm-value)
			 (just-c sizer opcode)))
	   (just-r2    (lambda (sizer partial-code-a partial-code-b reg)
			 (outc (+ partial-code-b reg))
			 (outc partial-code-a)
			 (check-size sizer)))
	   (just-r     (lambda (sizer partial-code reg)
			 (outc (+ partial-code reg))
			 (check-size sizer)))
	   (just-r-i   (lambda (sizer partial-code reg imm-value)
			 (handle-imm sizer imm-value)
			 (just-r sizer partial-code reg)))
	   (just-i-rel (lambda (sizer opcode rel-value)
			 (cond ((or (symbol? rel-value) (number? rel-value))
				(handle-rel-symbol sizer 'rel rel-value 0))
			       (else
				(apply handle-rel-symbol
				       (cons sizer (cdr rel-value)))))
			 (just-c sizer opcode)))
	   (just-m     (lambda (sizer opcode dest reg-field)
			 (handle-mem dest reg-field)
			 (just-c sizer opcode)))
	   (r/m        (lambda (sizer opcode dest reg-field)
			 (if (number? dest)
			     (handle-r/r dest reg-field)
			     (handle-mem dest reg-field))
			 (just-c sizer opcode)))
	   (r/m-i      (lambda (sizer opcode dest reg-field imm-value)
			 (handle-imm sizer imm-value)
			 (r/m sizer opcode dest reg-field)))
	   (r/m-i8     (lambda (sizer opcode dest reg-field imm-value)
			 (outc imm-value)
			 (r/m sizer opcode dest reg-field)))
	   (r/m-r      (lambda (sizer opcode dest src)
			 (if (number? dest)
			     (handle-r/r dest src)
			     (handle-mem dest src))
			 (just-c sizer opcode)))
	   (r-r/m      (lambda (sizer opcode dest src)
			 (r/m-r sizer opcode src dest)))
	   (r/m-r-i    (lambda (sizer opcode dest src imm)
			 (handle-imm sizer imm)
			 (r/m-r sizer opcode dest src)))
	   (r-r/m-i    (lambda (sizer opcode dest src imm)
			 (r/m-r-i sizer opcode src dest imm)))
	   (r/m-r-i8   (lambda (sizer opcode dest src imm)
			 (handle-imm 1 imm)
			 (r/m-r sizer opcode dest src)))
	   (r-r/m-i8   (lambda (sizer opcode dest src imm)
			 (r/m-r-i8 sizer opcode src dest imm)))
	   (i16-i8     (lambda (sizer opcode imm1 imm2)
			 (handle-imm 1 imm2)
			 (handle-imm 2 imm1)
			 (just-c sizer opcode)))
	   (i16-i16    (lambda (sizer opcode imm1 imm2)
			 (handle-imm 2 imm2)
			 (handle-imm 2 imm1)
			 (just-c sizer opcode)))
	   (i16-i32    (lambda (sizer opcode imm1 imm2)
			 (handle-imm 2 imm2)
			 (handle-imm 4 imm1)
			 (just-c sizer opcode))))
	(let
	    (
	     (gen-non
	      (lambda (sizer opcode)
		(meta-lambda
		 (begin (just-c sizer opcode)))))
	     
	     (gen-alu
	      (lambda (rm-op-b rm-op-dw rm/r-op-b
			       rm/r-op-dw i-op-b i-op-dw reg-field)
		(meta-lambda
		 (or
		  (and 'eax (or (and i8 (lambda (y)
					  (r/m-i8 4 131 0 reg-field y)))
				(and i32 (lambda (y) (just-i 4 i-op-dw y)))))
		  (and r32 (or (and r32 (lambda (x y) (r/m-r 4 rm-op-dw x y)))
			       (and i8 (lambda (x y)
					 (r/m-i8 4 131 x reg-field y)))
			       (and i32 (lambda (x y)
					  (r/m-i 4 129 x reg-field y)))
			       (and m32 (lambda (x y)
					  (r-r/m 4 rm/r-op-dw x y)))))
		  (and 'al  i8 (lambda (y) (just-i 1 i-op-b  y)))
		  (and r8 (or (and i8 (lambda (x y)
					(r/m-i 1 128 x reg-field y)))
			      (and r8 (lambda (x y) (r/m-r 1 rm-op-b x y)))
			      (and m8 (lambda (x y) (r-r/m 1 rm/r-op-b x y)))))
		  (and 'ax  i16 (lambda (y) (just-i 2 i-op-dw y)))
		  (and r16 (or (and r16 (lambda (x y)
					  (r/m-r 2 rm-op-dw x y)))
			       (and i8 (lambda (x y)
					 (r/m-i8 2 131 x reg-field y)))
			       (and i16 (lambda (x y)
					  (r/m-i 2 129 x reg-field y)))
			       (and m16 (lambda (x y)
					  (r-r/m 2 rm/r-op-dw x y)))))
		  (and m32 r32 (lambda (x y) (r/m-r 4 rm-op-dw x y)))
		  (and m16 r16 (lambda (x y) (r/m-r 2 rm-op-dw x y)))
		  (and m8  r8  (lambda (x y) (r/m-r 1 rm-op-b x y)))
		  (and em8 i8 (lambda (x y) (r/m-i  1 #x80 x reg-field y)))
		  (and em32 (or (and i8  (lambda (x y)
					   (r/m-i8 4 #x83 x reg-field y)))
				(and i32 (lambda (x y)
					   (r/m-i  4 #x81 x reg-field y)))))
		  (and em16 (or (and i8 (lambda (x y)
					  (r/m-i8 2 #x83 x reg-field y)))
				(and i16 (lambda (x y)
					   (r/m-i  2 #x81 x reg-field y)))))
		  (and um32
		       (or (and i8 (lambda (x y)
				     (if (= 16 (sassy-bits r))
					 (r/m-i8 2 #x83 x reg-field y)
					 (r/m-i8 4 #x83 x reg-field y))))
			   (and ei32 (lambda (x y)
				       (r/m-i  4 #x81 x reg-field y)))
			   (and ei16 (lambda (x y)
				       (r/m-i  2 #x81 x reg-field y)))
			   (and ui32
				(lambda (x y)
				  (if (and (ui16 y) (= 16 (sassy-bits r)))
				      (r/m-i  2 #x81 x reg-field y)
				      (r/m-i  4 #x81 x reg-field y))))))))))
	     (gen-bt
	      (lambda (opcode1 opcode2 reg-field)
		(meta-lambda
		 (or (and (or r32 em32)
			  (or (and r32 (lambda (x y) (r/m-r 4 opcode1 x y)))
			      (and i8  (lambda (x y)
					 (r/m-i8 4 opcode2 x reg-field y)))))
		     (and (or r16 em16)
			  (or (and r16 (lambda (x y) (r/m-r 2 opcode1 x y)))
			      (and i8
				   (lambda (x y)
				     (r/m-i8 2 opcode2 x reg-field y)))))
		     (and um16 r16 (lambda (x y) (r/m-r 2 opcode1 x y)))
		     (and um32 r32 (lambda (x y) (r/m-r 4 opcode1 x y)))
		     (and um32 i8 (lambda (x y)
				    (if (= 16 (sassy-bits r))
					(r/m-i8 2 opcode2 x reg-field y)
					(r/m-i8 4 opcode2 x reg-field y))))))))
	     (gen-shift
	      (lambda (reg-field)
		(meta-lambda
		 (or
		  (and (or r32 em32)
		       (or (and 1 (lambda (x) (r/m 4 #xd1 x reg-field)))
			   (and 'cl (lambda (x) (r/m 4 #xd3 x reg-field)))
			   (and i8 (lambda (x y)
				     (r/m-i8 4 #xc1 x reg-field y)))))
		  (and (or r8 em8)
		       (or (and 1 (lambda (x) (r/m 1 #xd0 x reg-field)))
			   (and 'cl (lambda (x) (r/m 1 #xd2 x reg-field)))
			   (and i8 (lambda (x y)
				     (r/m-i  1 #xc0 x reg-field y)))))
		  (and (or r16 em16)
		       (or (and 1 (lambda (x) (r/m 2 #xd1 x reg-field)))
			   (and 'cl (lambda (x) (r/m 2 #xd3 x reg-field)))
			   (and  i8 (lambda (x y)
				      (r/m-i8 2 #xc1 x reg-field y)))))
		  (and um32 ?
		       (lambda (x y)
			 (let ((sizer (/ (sassy-bits r) 8)))
			   (cond ((eq? 1 y) (r/m sizer #xd1 x reg-field))
				 ((eq? 'cl y) (r/m sizer #xd3 x reg-field))
				 ((i8 y) =>
				  (lambda (y)
				    (r/m-i8 sizer #xc1 x reg-field y)))
				 (else #f)))))))))
	     (gen-jcc
	      (lambda (cc-code)
		(meta-lambda
		 (or
		  (and (or erel8 (and 'short (or rel32 rel16 rel8)))
		       (lambda (x) (just-i-rel 1 (+ #x70 cc-code) x)))
		  (and (?* 'near)
		       (or (and erel32
				(lambda (x)
				  (just-i-rel 4 `(#x0f ,(+ #x80 cc-code)) x)))
			   (and erel16
				(lambda (x)
				  (just-i-rel 2 `(#x0f ,(+ #x80 cc-code)) x)))
			   (and urel32
				(lambda (x)
				  (if (and (urel16 x)
					   (= 16 (sassy-bits r)))
				      (just-i-rel 2 `(#x0f ,(+ #x80 cc-code)) x)
				      (just-i-rel
				       4 `(#x0f ,(+ #x80 cc-code)) x))))))))))
	     (gen-setcc
	      (lambda (cc-code)
		(meta-lambda
		 (and (or r8 m8) (lambda (x)
				   (r/m 1 `(#x0f ,(+ #x90 cc-code))
					x #b000))))))
	     (gen-cmovcc
	      (lambda (cc-code)
		(meta-lambda
		 (or (and r32 (or r32 m32)
			  (lambda (x y)
			    (r-r/m 4 `(#x0f ,(+ #x40 cc-code)) x y)))
		     (and r16 (or r16 m16)
			  (lambda (x y)
			    (r-r/m 2 `(#x0f ,(+ #x40 cc-code)) x y)))))))
	     (gen-decinc
	      (lambda (partial-code reg-field)
		(meta-lambda
		 (or (and r32 (lambda (x) (just-r 4 partial-code x)))
		     (and r16 (lambda (x) (just-r 2 partial-code x)))
		     (and em32 (lambda (x) (r/m 4 #xff x reg-field)))
		     (and em16 (lambda (x) (r/m 2 #xff x reg-field)))
		     (and um32 (lambda (x)
				 (if (= 16 (sassy-bits r))
				     (r/m 2 #xff x reg-field)
				     (r/m 4 #xff x reg-field))))
		     (and (or r8 em8) (lambda (x) (r/m 1 #xfe x reg-field)))))))
	     (gen-plier
	      (lambda (reg-field)
		(meta-lambda
		 (or (and (or r32 em32) (lambda (x) (r/m 4 #xf7 x reg-field)))
		     (and (or r16 em16) (lambda (x) (r/m 2 #xf7 x reg-field)))
		     (and (or r8   em8) (lambda (x) (r/m 1 #xf6 x reg-field)))
		     (and um32 (lambda (x)
				 (if (= 16 (sassy-bits r))
				     (r/m 2 #xf7 x reg-field)
				     (r/m 4 #xf7 x reg-field))))))))
	     (gen-load
	      (lambda (opcode)
		(meta-lambda
		 (or (and r32 m32 (lambda (x y) (r-r/m 4 opcode x y)))
		     (and r16 m16 (lambda (x y) (r-r/m 2 opcode x y)))))))
	     (gen-movx
	      (lambda (opcode1 opcode2)
		(meta-lambda
		 (or (and r32 (or (and (or r8 em8)
				       (lambda (x y)
					 (r-r/m 4 `(#x0f ,opcode1) x y)))
				  (and (or r16 m16)
				       (lambda (x y)
					 (r-r/m 4 `(#x0f ,opcode2) x y)))))
		     (and r16 (or r8 m8)
			  (lambda (x y) (r-r/m 2 `(#x0f ,opcode1) x y)))))))
	     (gen-r/rm
	      (lambda (opcodes)
		(meta-lambda
		 (or (and r32 (or r32 m32) (lambda (x y) (r-r/m 4 opcodes x y)))
		     (and r16 (or r16 m16) (lambda (x y)
					     (r-r/m 2 opcodes x y)))))))
	     (gen-rm
	      (lambda (opc reg-field)
		(meta-lambda
		 (and m32 (lambda (x) (r/m 1 `(#x0f ,opc) x reg-field))))))
	     (gen-rm8
	      (lambda (opc reg-field)
		(meta-lambda
		 (and m8 (lambda (x) (r/m 1 `(#x0f ,opc) x reg-field))))))
	     (gen-rm2
	      (lambda (opcodes reg-field)
		(meta-lambda
		 (and (or r16 m16) (lambda (x) (r/m 1 opcodes x reg-field))))))
	     (gen-aa
	      (lambda (opcodes-none opcodes-1)
		(meta-lambda
		 (or (begin (just-c 1 opcodes-none))
		     (and i8 (lambda (x) (just-i 1 opcodes-1 x)))))))
	     (gen-ret
	      (lambda (opcodes-none opcodes-1)
		(meta-lambda
		 (or (begin (just-c 1 opcodes-none))
		     (and i16 (lambda (x) (just-i 2 opcodes-1 x #f)))))))
	     (gen-doub-shift
	      (lambda (code1 code2)
		(meta-lambda
		 (or (and (or r32 m32) r32
			  (or (and i8 (lambda (x y z)
					(r/m-r-i8 4 `(#x0f ,code1) x y z)))
			      (and 'cl (lambda (x y)
					 (r/m-r 4 `(#x0f ,code2) x y)))))
		     (and (or r16 m16) r16
			  (or (and i8 (lambda (x y z)
					(r/m-r-i8 2 `(#x0f ,code1) x y z)))
			      (and 'cl (lambda (x y)
					 (r/m-r 2 `(#x0f ,code2) x y)))))))))
	     (gen-loop
	      (lambda (opcode)
		(meta-lambda
		 (and rel8 (or (lambda (x) (just-i-rel 1 opcode x))
			       (and 'cx
				    (lambda (x)
				      (if (= 16 (sassy-bits r))
					  (just-i-rel 1 opcode x)
					  (just-i-rel 1 `(#x67 ,opcode) x))))
			       (and 'ecx
				    (lambda (x)
				      (if (= 16 (sassy-bits r))
					  (just-i-rel 1 `(#x67 ,opcode) x)
					  (just-i-rel 1 opcode x)))))))))
					  
	     (gen-cmpx
	      (lambda (opcode1 opcode2)
		(meta-lambda
		 (or (and (or r8 m8)    r8 (lambda (x y) (r/m-r 1 opcode1 x y)))
		     (and (or r16 m16) r16 (lambda (x y) (r/m-r 2 opcode2 x y)))
		     (and (or r32 m32) r32 (lambda (x y)
					     (r/m-r 4 opcode2 x y)))))))
	     (gen-fpmath-1
	      (lambda (reg-field to-0-c from-0-c)
		(meta-lambda
		 (or (and em64 (lambda (x) (r/m 1 #xdc x reg-field)))
		     (and m32 (lambda (x) (r/m 1 #xd8 x reg-field)))
		     (and 'st0 st (lambda (x) (just-r2 1 #xd8 to-0-c x)))
		     (and st 'st0 (lambda (x) (just-r2 1 #xdc from-0-c x)))))))
	     (gen-fpmath-2
	      (lambda (with w/o)
		(meta-lambda
		 (or (begin (just-c 1 `(#xde ,w/o)))
		     (and st 'st0 (lambda (x) (just-r2 1 #xde with x)))))))
	     (gen-fpmath-3
	      (lambda (reg-field)
		(meta-lambda
		 (or (and em16 (lambda (x) (r/m 1 #xde x reg-field)))
		     (and m32 (lambda (x) (r/m 1 #xda x reg-field)))))))
	     (gen-fcmovcc
	      (lambda (p-code-1 p-code-2)
		(meta-lambda
		 (and 'st0 st (lambda (x) (just-r2 1 p-code-1 p-code-2 x))))))
	     (gen-fp-reg/non
	      (lambda (op1-a op1-b opcode2)
		(meta-lambda
		 (or (begin (just-c 1 opcode2))
		     (and st (lambda (x) (just-r2 1 op1-a op1-b x)))))))
	     (gen-fp-3m/st
	      (lambda (reg-field1 reg-field2 st-opcode-a st-opcode-b)
		(meta-lambda
		 (or (and em64 (lambda (x) (r/m 1 #xdd x reg-field1)))
		     (and em80 (lambda (x) (r/m 1 #xdb x reg-field2)))
		     (and m32 (lambda (x) (r/m 1 #xd9 x reg-field1)))
		     (and st  (lambda (x)
				(just-r2 1 st-opcode-a st-opcode-b x)))))))
	     (gen-fp-3int
	      (lambda (reg-field1 reg-field2)
		(meta-lambda
		 (or (and em64 (lambda (x) (r/m 1 '#xdf x reg-field2)))
		     (and em16 (lambda (x) (r/m 1 '#xdf x reg-field1)))
		     (and m32 (lambda (x) (r/m 1 '#xdb x reg-field1)))))))
	     (gen-fp-2int
	      (lambda (opcode1 opcode2 reg-field)
		(meta-lambda
		 (or (and em16 (lambda (x) (r/m 1 opcode1 x reg-field)))
		     (and m32 (lambda (x) (r/m 1 opcode2 x reg-field)))))))
	     (gen-fp-com
	      (lambda (pcode1 pcode2 reg-field)
		(meta-lambda
		 (or (begin (just-c 1 `(#xd8 ,pcode2)))
		     (and em64 (lambda (x) (r/m 1 #xdc x reg-field)))
		     (and m32 (lambda (x) (r/m 1 #xd8 x reg-field)))
		     (and st  (lambda (x) (just-r2 1 #xd8 pcode1 x)))))))
	     (gen-mmx-log
	      (lambda (opcode)
		(meta-lambda
		 (or (and mm (or mm m64)
			  (lambda (x y) (r-r/m 1 `(#x0f ,opcode) x y)))
		     (and xmm (or xmm m128)
			  (lambda (x y) (r-r/m 1 `(#x66 #x0f ,opcode) x y)))))))
	     (gen-mmx-unplow
	      (lambda (opcode)
		(meta-lambda
		 (or (and mm (or mm m32)
			  (lambda (x y) (r-r/m 1 `(#x0f ,opcode) x y)))
		     (and xmm (or xmm m128)
			  (lambda (x y) (r-r/m 1 `(#x66 #x0f ,opcode) x y)))))))
	     (gen-mmx-shr
	      (lambda (opcode1 opcode2 reg-field)
		(meta-lambda
		 (or
		  (and mm (or (and (or mm  m64)
				   (lambda (x y)
				     (r-r/m 1 `(#x0f ,opcode1) x y)))
			      (and i8
				   (lambda (x y)
				     (r/m-i8 1 `(#x0f ,opcode2)
					     x reg-field y)))))
		  (and xmm (or (and (or xmm m128)
				    (lambda (x y)
				      (r-r/m 1 `(#x66 #x0f ,opcode1) x y)))
			       (and i8
				    (lambda (x y)
				      (r/m-i8 1 `(#x66 #x0f ,opcode2)
					      x reg-field y)))))))))
	     (gen-sse1-mov
	      (lambda (opcode1 opcode2)
		(meta-lambda
		 (or (and xmm (or xmm m128) (lambda (x y)
					      (r-r/m 1 opcode1 x y)))
		     (and m128 xmm (lambda (x y) (r/m-r 1 opcode2 x y)))))))
	     (gen-sse-ps/pd
	      (lambda (opcode)
		(meta-lambda
		 (and xmm (or xmm m128) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse1-ss
	      (lambda (opcode)
		(meta-lambda
		 (and xmm (or xmm m32) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse2-sd
	      (lambda (opcode)
		(meta-lambda
		 (and xmm (or xmm m64) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse1-mov2
	      (lambda (opcode1 opcode2)
		(meta-lambda
		 (or (and xmm m64 (lambda (x y) (r-r/m 1 opcode1 x y)))
		     (and m64 xmm (lambda (x y) (r/m-r 1 opcode2 x y)))))))
	     (gen-xmm-r/r
	      (lambda (opcode)
		(meta-lambda
		 (and xmm xmm (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse-cmp
	      (lambda (opcode)
		(meta-lambda
		 (and xmm (or xmm m128) i8
		      (lambda (x y z) (r-r/m-i 1 opcode x y z))))))
	     (gen-sse1-ps2pi
	      (lambda (opc)
		(meta-lambda
		 (and mm (or xmm m64) (lambda (x y)
					(r-r/m 1 `(#x0f ,opc) x y))))))
	     (gen-sse1-ss2si
	      (lambda (opc)
		(meta-lambda
		 (and r32 (or xmm m32) (lambda (x y)
					 (r-r/m 1 `(#xf3 #x0f ,opc) x y))))))
	     (gen-sse2-sd2si
	      (lambda (opcode)
		(meta-lambda
		 (and r32 (or xmm m64) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse-movmsk
	      (lambda (opcode)
		(meta-lambda
		 (and r32 xmm (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse-pd2pi
	      (lambda (opcode)
		(meta-lambda
		 (and mm (or xmm m128) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse-pi2pds
	      (lambda (opcode)
		(meta-lambda
		 (and xmm (or mm m64) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse-si2sssd
	      (lambda (opcode)
		(meta-lambda
		 (and xmm (or r32 m32) (lambda (x y) (r-r/m 1 opcode x y))))))
	     (gen-sse2-sr
	      (lambda (reg-field)
		(meta-lambda
		 (and xmm i8 (lambda (x y)
			       (r/m-i 1 '(#x66 #x0f #x73) x reg-field y))))))
	     (gen-sse-movnt
	      (lambda (opcode)
		(meta-lambda
		 (and m128 xmm (lambda (x y) (r/m-r 1 opcode x y))))))
	     (gen-prefix
	      (lambda (pred code)
		(meta-lambda
		 (and pred (lambda (x)
			     (and ((hash-table-ref the-opcodes (car x)) (cdr x))
				  (outc code))))))))
	  (alist->hash-table
	   `(
	     (rep   . ,(gen-prefix rep-able #xf3))
	     (repe  . ,(gen-prefix rep-e-able #xf3))
	     (repz  . ,(gen-prefix rep-e-able #xf3))
	     (repne . ,(gen-prefix rep-e-able #xf2))
	     (repnz . ,(gen-prefix rep-e-able #xf2))
	     (lock  . ,(gen-prefix lock-able  #xf0))
	     (brt   . ,(gen-prefix branch-predict-able #x3e))
	     (brnt  . ,(gen-prefix branch-predict-able #x2e))
	     (aaa      . ,(gen-non 1 #x37))
	     (aas      . ,(gen-non 1 #x3f))
	     (cbw      . ,(gen-non 2 #x98))
	     (cdq      . ,(gen-non 4 #x99))
	     (clc      . ,(gen-non 1 #xf8))
	     (cld      . ,(gen-non 1 #xfc))
	     (cli      . ,(gen-non 1 #xfa))
	     (clts     . ,(gen-non 1 '(#x0f #x06)))
	     (cmc      . ,(gen-non 1 #xf5))
	     (cmpsb    . ,(gen-non 1 #xa6))
	     (cmpsw    . ,(gen-non 2 #xa7)) ;cmpsd in sse2
	     (cpuid    . ,(gen-non 1 '(#x0f #xa2)))
	     (cwde     . ,(gen-non 4 #x98))
	     (cwd      . ,(gen-non 2 #x99))
	     (daa      . ,(gen-non 1 #x27))
	     (das      . ,(gen-non 1 #x2f))
	     (hlt      . ,(gen-non 1 #xf4))
	     (insb     . ,(gen-non 1 #x6c))
	     (insw     . ,(gen-non 2 #x6d))
	     (insd     . ,(gen-non 4 #x6d))
	     (int3     . ,(gen-non 1 #xcc))
	     (into     . ,(gen-non 1 #xce))
	     (invd     . ,(gen-non 1 '(#x0f #x08)))
	     (iret     . ,(gen-non 1 #xcf))
	     (iretw    . ,(gen-non 2 #xcf))
	     (iretd    . ,(gen-non 4 #xcf))
	     (lahf     . ,(gen-non 1 #x9f))
	     (leave    . ,(gen-non 1 #xc9))
	     (lodsb    . ,(gen-non 1 #xac))
	     (lodsw    . ,(gen-non 2 #xad))
	     (lodsd    . ,(gen-non 4 #xad))
	     (movsb    . ,(gen-non 1 #xa4))
	     (movsw    . ,(gen-non 2 #xa5)) ;movsd in sse2
	     (nop      . ,(gen-non 1 #x90))
	     (outsb    . ,(gen-non 1 #x6e))
	     (outsw    . ,(gen-non 2 #x6f))
	     (outsd    . ,(gen-non 4 #x6f))
	     (popa     . ,(gen-non 1 #x61))
	     (popaw    . ,(gen-non 2 #x61))
	     (popad    . ,(gen-non 4 #x61))
	     (popf     . ,(gen-non 1 #x9d))
	     (popfw    . ,(gen-non 2 #x9d))
	     (popfd    . ,(gen-non 4 #x9d))
	     (pusha    . ,(gen-non 1 #x60))
	     (pushaw   . ,(gen-non 2 #x60))
	     (pushad   . ,(gen-non 4 #x60))
	     (pushf    . ,(gen-non 1 #x9c))
	     (pushfw   . ,(gen-non 2 #x9c))
	     (pushfd   . ,(gen-non 4 #x9c))
	     (rdmsr    . ,(gen-non 1 '(#x0f #x32)))
	     (rdpmc    . ,(gen-non 1 '(#x0f #x33)))
	     (rdtsc    . ,(gen-non 1 '(#x0f #x31)))
	     (rsm      . ,(gen-non 1 '(#x0f #xaa)))
	     (sahf     . ,(gen-non 1 #x9e))
	     (scasb    . ,(gen-non 1 #xae))
	     (scasw    . ,(gen-non 2 #xaf))
	     (scasd    . ,(gen-non 4 #xaf))
	     (stc      . ,(gen-non 1 #xf9))
	     (std      . ,(gen-non 1 #xfd))
	     (sti      . ,(gen-non 1 #xfb))
	     (stosb    . ,(gen-non 1 #xaa))
	     (stosw    . ,(gen-non 2 #xab))
	     (stosd    . ,(gen-non 4 #xab))
	     (sysenter . ,(gen-non 1 '(#x0f #x34)))
	     (sysexit  . ,(gen-non 1 '(#x0f #x35)))
	     (ud2      . ,(gen-non 1 '(#x0f #x0b)))
	     (wbinvd   . ,(gen-non 1 '(#x0f #x09)))
	     (wrmsr    . ,(gen-non 1 '(#x0f #x30)))
	     (xlat     . ,(gen-non 1 #xd7))
	     (xlatb    . ,(gen-non 1 #xd7))
	     (fld1     . ,(gen-non 1 '(#xd9 #xe8)))
	     (fldl2t   . ,(gen-non 1 '(#xd9 #xe9)))
	     (fldl2e   . ,(gen-non 1 '(#xd9 #xea)))
	     (fldpi    . ,(gen-non 1 '(#xd9 #xeb)))
	     (fldlg2   . ,(gen-non 1 '(#xd9 #xec)))
	     (fldln2   . ,(gen-non 1 '(#xd9 #xed)))
	     (fldz     . ,(gen-non 1 '(#xd9 #xee)))
	     (fsin     . ,(gen-non 1 '(#xd9 #xfe)))
	     (fcos     . ,(gen-non 1 '(#xd9 #xff)))
	     (fsincos  . ,(gen-non 1 '(#xd9 #xfb)))
	     (fptan    . ,(gen-non 1 '(#xd9 #xf2)))
	     (fpatan   . ,(gen-non 1 '(#xd9 #xf3)))
	     (f2xm1    . ,(gen-non 1 '(#xd9 #xf0)))
	     (fyl2x    . ,(gen-non 1 '(#xd9 #xf1)))
	     (fyl2xp1  . ,(gen-non 1 '(#xd9 #xf9)))
	     (fincstp  . ,(gen-non 1 '(#xd9 #xf7)))
	     (fdecstp  . ,(gen-non 1 '(#xd9 #xf6)))
	     (finit    . ,(gen-non 1 '(#x9b #xdb #xe3)))
	     (fninit   . ,(gen-non 1 '(#xdb #xe3)))
	     (fclex    . ,(gen-non 1 '(#x9b #xdb #xe2)))
	     (fnclex   . ,(gen-non 1 '(#xdb #xe2)))
	     (fnop     . ,(gen-non 1 '(#xd9 #xd0)))
	     (fcompp   . ,(gen-non 1 '(#xde #xd9)))
	     (fucompp  . ,(gen-non 1 '(#xda #xe9)))
	     (ftst     . ,(gen-non 1 '(#xd9 #xe4)))
	     (fxam     . ,(gen-non 1 '(#xd9 #xe5)))
	     (fprem    . ,(gen-non 1 '(#xd9 #xf8)))
	     (fprem1   . ,(gen-non 1 '(#xd9 #xf5)))
	     (fabs     . ,(gen-non 1 '(#xd9 #xe1)))
	     (fchs     . ,(gen-non 1 '(#xd9 #xe0)))
	     (frndint  . ,(gen-non 1 '(#xd9 #xfc)))
	     (fscale   . ,(gen-non 1 '(#xd9 #xfd)))
	     (fsqrt    . ,(gen-non 1 '(#xd9 #xfa)))
	     (fxtract  . ,(gen-non 1 '(#xd9 #xf4)))
	     (fwait    . ,(gen-non 1 #x9b))
	     (wait     . ,(gen-non 1 #x9b))
	     (emms     . ,(gen-non 1 '(#x0f #x77)))
	     (adc . ,(gen-alu #x10 #x11 #x12 #x13 #x14 #x15 #b010))
	     (add . ,(gen-alu #x00 #x01 #x02 #x03 #x04 #x05 #b000))
	     (and . ,(gen-alu #x20 #x21 #x22 #x23 #x24 #x25 #b100))
	     (cmp . ,(gen-alu #x38 #x39 #x3a #x3b #x3c #x3d #b111))
	     (or  . ,(gen-alu #x08 #x09 #x0a #x0b #x0c #x0d #b001))
	     (sbb . ,(gen-alu #x18 #x19 #x1a #x1b #x1c #x1d #b011))
	     (sub . ,(gen-alu #x28 #x29 #x2a #x2b #x2c #x2d #b101))
	     (xor . ,(gen-alu #x30 #x31 #x32 #x33 #x34 #x35 #b110))
	     (bt  . ,(gen-bt '(#x0f #xa3) '(#x0f #xba) #b100))
	     (btc . ,(gen-bt '(#x0f #xbb) '(#x0f #xba) #b111))
	     (btr . ,(gen-bt '(#x0f #xb3) '(#x0f #xba) #b110))
	     (bts . ,(gen-bt '(#x0f #xab) '(#x0f #xba) #b101))
	     (rcl . ,(gen-shift #b010))
	     (rcr . ,(gen-shift #b011))
	     (rol . ,(gen-shift #b000))
	     (ror . ,(gen-shift #b001))
	     (sal . ,(gen-shift #b100))
	     (sar . ,(gen-shift #b111))
	     (shl . ,(gen-shift #b100))
	     (shr . ,(gen-shift #b101))
	     (jo   . ,(gen-jcc #x00))
	     (jno  . ,(gen-jcc #x01))
	     (jb   . ,(gen-jcc #x02))
	     (jc   . ,(gen-jcc #x02))
	     (jnae . ,(gen-jcc #x02))
	     (jnb  . ,(gen-jcc #x03))
	     (jnc  . ,(gen-jcc #x03))
	     (jae  . ,(gen-jcc #x03))
	     (je   . ,(gen-jcc #x04))
	     (jz   . ,(gen-jcc #x04))
	     (jne  . ,(gen-jcc #x05))
	     (jnz  . ,(gen-jcc #x05))
	     (jbe  . ,(gen-jcc #x06))
	     (jna  . ,(gen-jcc #x06))
	     (ja   . ,(gen-jcc #x07))
	     (jnbe . ,(gen-jcc #x07))
	     (js   . ,(gen-jcc #x08))
	     (jns  . ,(gen-jcc #x09))
	     (jp   . ,(gen-jcc #x0a))  
	     (jpe  . ,(gen-jcc #x0a))  
	     (jnp  . ,(gen-jcc #x0b))  
	     (jpo  . ,(gen-jcc #x0b))  
	     (jl   . ,(gen-jcc #x0c))
	     (jnge . ,(gen-jcc #x0c))
	     (jge  . ,(gen-jcc #x0d))
	     (jnl  . ,(gen-jcc #x0d))
	     (jle  . ,(gen-jcc #x0e))
	     (jng  . ,(gen-jcc #x0e))
	     (jnle . ,(gen-jcc #x0f))
	     (jg   . ,(gen-jcc #x0f))
	     (cmovo   . ,(gen-cmovcc #x00))
	     (cmovno  . ,(gen-cmovcc #x01))
	     (cmovb   . ,(gen-cmovcc #x02))
	     (cmovc   . ,(gen-cmovcc #x02))
	     (cmovnae . ,(gen-cmovcc #x02))
	     (cmovnb  . ,(gen-cmovcc #x03))
	     (cmovnc  . ,(gen-cmovcc #x03))
	     (cmovae  . ,(gen-cmovcc #x03))
	     (cmove   . ,(gen-cmovcc #x04))
	     (cmovz   . ,(gen-cmovcc #x04))
	     (cmovne  . ,(gen-cmovcc #x05))
	     (cmovnz  . ,(gen-cmovcc #x05))
	     (cmovbe  . ,(gen-cmovcc #x06))
	     (cmovna  . ,(gen-cmovcc #x06))
	     (cmova   . ,(gen-cmovcc #x07))
	     (cmovnbe . ,(gen-cmovcc #x07))
	     (cmovs   . ,(gen-cmovcc #x08))
	     (cmovns  . ,(gen-cmovcc #x09))
	     (cmovp   . ,(gen-cmovcc #x0a))  
	     (cmovpe  . ,(gen-cmovcc #x0a))  
	     (cmovnp  . ,(gen-cmovcc #x0b))  
	     (cmovpo  . ,(gen-cmovcc #x0b))  
	     (cmovl   . ,(gen-cmovcc #x0c))
	     (cmovnge . ,(gen-cmovcc #x0c))
	     (cmovge  . ,(gen-cmovcc #x0d))
	     (cmovnl  . ,(gen-cmovcc #x0d))
	     (cmovle  . ,(gen-cmovcc #x0e))
	     (cmovng  . ,(gen-cmovcc #x0e))
	     (cmovnle . ,(gen-cmovcc #x0f))
	     (cmovg   . ,(gen-cmovcc #x0f))
	     (seto   . ,(gen-setcc #x00))
	     (setno  . ,(gen-setcc #x01))
	     (setb   . ,(gen-setcc #x02))
	     (setc   . ,(gen-setcc #x02))
	     (setnae . ,(gen-setcc #x02))
	     (setnb  . ,(gen-setcc #x03))
	     (setnc  . ,(gen-setcc #x03))
	     (setae  . ,(gen-setcc #x03))
	     (sete   . ,(gen-setcc #x04))
	     (setz   . ,(gen-setcc #x04))
	     (setne  . ,(gen-setcc #x05))
	     (setnz  . ,(gen-setcc #x05))
	     (setbe  . ,(gen-setcc #x06))
	     (setna  . ,(gen-setcc #x06))
	     (seta   . ,(gen-setcc #x07))
	     (setnbe . ,(gen-setcc #x07))
	     (sets   . ,(gen-setcc #x08))
	     (setns  . ,(gen-setcc #x09))
	     (setp   . ,(gen-setcc #x0a))  
	     (setpe  . ,(gen-setcc #x0a))  
	     (setnp  . ,(gen-setcc #x0b))  
	     (setpo  . ,(gen-setcc #x0b))  
	     (setl   . ,(gen-setcc #x0c))
	     (setnge . ,(gen-setcc #x0c))
	     (setge  . ,(gen-setcc #x0d))
	     (setnl  . ,(gen-setcc #x0d))
	     (setle  . ,(gen-setcc #x0e))
	     (setng  . ,(gen-setcc #x0e))
	     (setnle . ,(gen-setcc #x0f))
	     (setg   . ,(gen-setcc #x0f))
	     (dec . ,(gen-decinc #x48 #b001))
	     (inc . ,(gen-decinc #x40 #b000))
	     (div  . ,(gen-plier #b110))
	     (idiv . ,(gen-plier #b111))
	     (mul  . ,(gen-plier #b100))
	     (neg  . ,(gen-plier #b011))
	     (not  . ,(gen-plier #b010))
	     (lds . ,(gen-load #xc5))
	     (les . ,(gen-load #xc4))
	     (lea . ,(gen-load #x8d))
	     (lfs . ,(gen-load '(#x0f #xb4)))
	     (lgs . ,(gen-load '(#x0f #xb5)))
	     (lss . ,(gen-load '(#x0f #xb2)))
	     (movsx . ,(gen-movx #xbe #xbf))
	     (movzx . ,(gen-movx #xb6 #xb7))
	     (lldt . ,(gen-rm2 '(#x0f #x00) #b010))
	     (sldt . ,(gen-rm2 '(#x0f #x00) #b000))
	     (lmsw . ,(gen-rm2 '(#x0f #x01) #b110))
	     (smsw . ,(gen-rm2 '(#x0f #x01) #b100))
	     (ltr  . ,(gen-rm2 '(#x0f #x00) #b011))
	     (str  . ,(gen-rm2 '(#x0f #x00) #b001))
	     (verr . ,(gen-rm2 '(#x0f #x00) #b100))
	     (verw . ,(gen-rm2 '(#x0f #x00) #b101))
	     (invlpg . ,(gen-rm  #x01 #b111))
	     (lgdt   . ,(gen-rm  #x01 #b010))
	     (sgdt   . ,(gen-rm  #x01 #b000))
	     (lidt   . ,(gen-rm  #x01 #b011))
	     (sidt   . ,(gen-rm  #x01 #b001))
	     (bsf . ,(gen-r/rm '(#x0f #xbc)))
	     (bsr . ,(gen-r/rm '(#x0f #xbd)))
	     (lar . ,(gen-r/rm '(#x0f #x02)))
	     (lsl . ,(gen-r/rm '(#x0f #x03)))
	     (aad . ,(gen-aa '(#xd5 #x0a) #xd5))
	     (aam . ,(gen-aa '(#xd4 #x0a) #xd4))
	     (ret  . ,(gen-ret #xc3 #xc2))
	     (retn . ,(gen-ret #xc3 #xc2))
	     (retf . ,(gen-ret #xcb #xca))
	     (shld . ,(gen-doub-shift #xa4 #xa5))
	     (shrd . ,(gen-doub-shift #xac #xad))
	     (loop   . ,(gen-loop #xe2))
	     (loope  . ,(gen-loop #xe1))
	     (loopz  . ,(gen-loop #xe1))
	     (loopne . ,(gen-loop #xe0))
	     (loopnz . ,(gen-loop #xe0))
	     (cmpxchg . ,(gen-cmpx '(#x0f #xb0) '(#x0f #xb1)))
	     (xadd    . ,(gen-cmpx '(#x0f #xc0) '(#x0f #xc1)))
	     (arpl . ,(meta-lambda
		       (and (or r16 m16) r16 (lambda (x y)
					       (r/m-r 1 #x63 x y)))))
	     (bound . ,(meta-lambda
			(or (and r16 m16 (lambda (x y) (r-r/m 2 #x62 x y)))
			    (and r32 m32 (lambda (x y) (r-r/m 4 #x62 x y))))))
	     (bswap  . ,(meta-lambda
			 (and r32 (lambda (x) (just-r2 4 #x0f #xc8 x)))))
	     (cmpxchg8b . ,(meta-lambda
			    (and m32 (lambda (x)
				       (just-m 1 '(#x0f #xc7) x #b001)))))
	     (xchg . ,(meta-lambda
		       (or
			(and 'eax (or (and r32 (lambda (y) (just-r 4 #x90 y)))))
			(and r32 (or (and 'eax (lambda (y) (just-r 4 #x90 y)))
				     (and (or r32 m32)
					  (lambda (x y) (r-r/m 4 #x87 x y)))))
			(and 'ax r16 (lambda (y) (just-r 2 #x90 y)))
			(and r16 (or (and 'ax (lambda (y) (just-r 2 #x90 y)))
				     (and (or r16 m16)
					  (lambda (x y) (r-r/m 2 #x87 x y)))))
			(and r8 (or r8 m8) (lambda (x y) (r-r/m 1 #x86 x y)))
			(and m8 r8 (lambda (x y) (r/m-r 1 #x86 x y)))
			(and m16 r16 (lambda (x y) (r/m-r 2 #x87 x y)))
			(and m32 r32 (lambda (x y) (r/m-r 4 #x87 x y))))))
	     (enter . ,(meta-lambda
			(and i16 i8 (lambda (x y) (i16-i8 1 #xc8 x y)))))
	     (jcxz  . ,(meta-lambda
			(and rel8 (lambda (x)
				    (if (= 16 (sassy-bits r))
					(just-i-rel 1 #xe3 x)
					(just-i-rel 1 '(#x67 #xe3) x))))))
	     (jecxz . ,(meta-lambda
			(and rel8 (lambda (x)
				    (if (= 16 (sassy-bits r))
					(just-i-rel 1 '(#x67 #xe3) x)
					(just-i-rel 1 #xe3 x))))))
	     (in . ,(meta-lambda
		     (or
		      (and 'al (or (and i8 (lambda (y) (just-i8 1 #xe4 y)))
				   (and 'dx (begin (just-c 1 #xec)))))
		      (and 'ax (or (and i8 (lambda (y) (just-i8 2 #xe5 y)))
				   (and 'dx (begin (just-c 2 #xed)))))
		      (and 'eax (or (and i8 (lambda (y) (just-i8 4 #xe5 y)))
				    (and 'dx (begin (just-c 4 #xed))))))))
	     (out . ,(meta-lambda
		      (or
		       (and i8 (or (and 'al (lambda (x) (just-i8 1 #xe6 x)))
				   (and 'ax (lambda (x) (just-i8 2 #xe7 x)))
				   (and 'eax (lambda (x) (just-i8 4 #xe7 x)))))
		       (and 'dx (or (and 'al (begin (just-c 1 #xee)))
				    (and 'ax (begin (just-c 2 #xef)))
				    (and 'eax (begin (just-c 4 #xef))))))))
	     (int . ,(meta-lambda
		      (and i8 (lambda (x) (just-i8 1 #xcd x)))))
	     (pop . ,(meta-lambda
		      (or (and r16 (lambda (x) (just-r 2 #x58 x)))
			  (and r32 (lambda (x) (just-r 4 #x58 x)))
			  (and em32 (lambda (x) (just-m 4 #x8f x #b000)))
			  (and em16 (lambda (x) (just-m 2 #x8f x #b000)))
			  (and um32 (lambda (x)
				      (if (= 16 (sassy-bits r))
					  (just-m 2 #x8f x #b000)
					  (just-m 4 #x8f x #b000))))
			  (and 'ds (begin (just-c 1 #x1f)))
			  (and 'es (begin (just-c 1 #x07)))
			  (and 'ss (begin (just-c 1 #x17)))
			  (and 'fs (begin (just-c 1 '(#x0f #xa1))))
			  (and 'gs (begin (just-c 1 '(#x0f #xa9)))))))
	     (push . ,(meta-lambda
		       (or (and r32 (lambda (x) (just-r 4 #x50 x)))
			   (and r16 (lambda (x) (just-r 2 #x50 x)))
			   (and i8  (lambda (x) (just-i 1 #x6a x)))
			   (and ei32 (lambda (x) (just-i 4 #x68 x)))
			   (and ei16 (lambda (x) (just-i 2 #x68 x)))
			   (and ui32 (lambda (x)
				      (if (and (ui16 x)
					       (= 16 (sassy-bits r)))
					  (just-i 2 #x68 x)
					  (just-i 4 #x68 x))))
			   (and em32 (lambda (x) (just-m 4 #xff x #b110)))
			   (and em16 (lambda (x) (just-m 2 #xff x #b110)))
			   (and um32 (lambda (x)
				       (if (= 16 (sassy-bits r))
					   (just-m 2 #xff x #b110)
					   (just-m 4 #xff x #b110))))
			   (and 'cs (begin (just-c 1 #x0e)))
			   (and 'ds (begin (just-c 1 #x1e)))
			   (and 'es (begin (just-c 1 #x06)))
			   (and 'ss (begin (just-c 1 #x16)))
			   (and 'fs (begin (just-c 1 '(#x0f #xa0))))
			   (and 'gs (begin (just-c 1 '(#x0f #xa8)))))))
	     (imul . ,(meta-lambda
		       (or
			(and r32
			     (or (lambda (x) (r/m 4 247 x 5))
				 (and (or r32 m32)
				      (or (lambda (x y) (r-r/m 4 '(15 175) x y))
					  (and i8 (lambda (x y z)
						    (r-r/m-i8 4 107 x y z)))
					  (and i32 (lambda (x y z)
						     (r-r/m-i 4 105 x y z)))))
				 (and i8 (lambda (x y)
					   (r-r/m-i8 4 107 x x y)))
				 (and i32 (lambda (x y)
					    (r-r/m-i 4 105 x x y)))))
			(and r16
			     (or (lambda (x) (r/m 2 247 x 5))
				 (and (or r16 m16)
				      (or (lambda (x y) (r-r/m 2 '(15 175) x y))
					  (and i8 (lambda (x y z)
						    (r-r/m-i8 2 107 x y z)))
					  (and i16 (lambda (x y z)
						     (r-r/m-i 2 105 x y z)))))
				 (and i8 (lambda (x y)
					   (r-r/m-i8 2 107 x x y)))
				 (and i16 (lambda (x y)
					    (r-r/m-i 2 105 x x y)))))
			(and em32 (lambda (x) (r/m 4 #xf7 x #b101)))
			(and em16 (lambda (x) (r/m 2 #xf7 x #b101)))
			(and um32 (lambda (x)
				    (if (= 16 (sassy-bits r))
					(r/m 2 #xf7 x #b101)
					(r/m 4 #xf7 x #b101))))
			(and (or r8 m8) (lambda (x) (r/m 1 #xf6 x #b101))))))
	     (test . ,(meta-lambda
		       (or
			(and 'eax i32 (lambda (y) (just-i 4 #xa9 y)))
			(and 'al  i8  (lambda (y) (just-i 1 #xa8 y)))
			(and 'ax  i16 (lambda (y) (just-i 2 #xa9 y)))
			(and (or r8  em8)
			     (or (and r8 (lambda (x y) (r/m-r 1 #x84 x y)))
				 (and i8 (lambda (x y)
					   (r/m-i 1 #xf6 x #b000 y)))))
			(and um8 r8 (lambda (x y) (r/m-r 1 #x84 x y)))
			(and (or r32 em32)
			     (or (and r32 (lambda (x y) (r/m-r 4 #x85 x y)))
				 (and i32 (lambda (x y)
					    (r/m-i 4 #xf7 x #b000 y)))))
			(and (or r16 em16)
			     (or (and r16 (lambda (x y) (r/m-r 2 #x85 x y)))
				 (and i16 (lambda (x y)
					    (r/m-i 2 #xf7 x #b000 y)))))
			(and um32 r32 (lambda (x y) (r/m-r 4 #x85 x y)))
			(and um16 r16 (lambda (x y) (r/m-r 2 #x85 x y)))
			(and um32 ei32 (lambda (x y) (r/m-i 4 #xf7 x #b000 y)))
			(and um16 ei16 (lambda (x y) (r/m-i 2 #xf7 x #b000 y)))
			(and um32 ui32 (lambda (x y)
					 (if (and (ui16 y)
						  (= 16 (sassy-bits r)))
					     (r/m-i 2 #xf7 x #b000 y)
					     (r/m-i 4 #xf7 x #b000 y)))))))
	     (mov . ,(meta-lambda
		      (or
		       (and 'eax mi32 (lambda (y) (just-i32 4 #xa1 y)))
		       (and mi32 'eax (lambda (x) (just-i32 4 #xa3 x)))
		       (and 'al mi8   (lambda (y) (just-i32 1 #xa0 y)))
		       (and mi8 'al   (lambda (x) (just-i32 1 #xa2 x)))
		       (and 'ax mi16  (lambda (y) (just-i32 2 #xa1 y)))
		       (and mi16 'ax  (lambda (x) (just-i32 2 #xa3 x)))
		       (and r32 (or (and r32 (lambda (x y) (r/m-r 4 137 x y)))
				    (and m32 (lambda (x y) (r-r/m 4 139 x y)))
				    (and i32 (lambda (x y)
					       (just-r-i 4 184 x y)))
				    (and sreg-not-cs (lambda (x y)
						       (r/m-r 4 140 x y)))
				    (and creg (lambda (x y)
						(r/m-r 1 '(15 32) x y)))
				    (and dreg (lambda (x y)
						(r/m-r 1 '(15 33) x y)))))
		       (and r16 (or (and r16 (lambda (x y) (r/m-r 2 137 x y)))
				    (and m16 (lambda (x y) (r-r/m 2 139 x y)))
				    (and i16 (lambda (x y)
					       (just-r-i 2 184 x y)))
				    (and sreg-not-cs (lambda (x y)
						       (r/m-r 2 140 x y)))))
		       (and r8 (or (and r8 (lambda (x y) (r/m-r 1 136 x y)))
				   (and m8 (lambda (x y) (r-r/m 1 138 x y)))
				   (and i8 (lambda (x y)
					     (just-r-i 1 176 x y)))))
		       (and creg r32 (lambda (x y) (r/m-r 1 '(#x0f #x22) y x)))
		       (and dreg r32 (lambda (x y) (r/m-r 1 '(#x0f #x23) y x)))
		       (and m32 (or (and r32 (lambda (x y) (r/m-r 4 #x89 x y)))
				    (and i32 (lambda (x y)
					       (r/m-i 4 #xc7 x #b000 y)))))
		       (and m8 (or (and r8 (lambda (x y) (r/m-r 1 #x88 x y)))
				   (and i8 (lambda (x y)
					     (r/m-i 1 #xc6 x #b000 y)))))
		       (and m16 (or (and r16 (lambda (x y) (r/m-r 2 #x89 x y)))
				    (and i16 (lambda (x y)
					       (r/m-i 2 #xc7 x #b000 y)))))
		       (and sreg-not-cs
			    (or (and (or r32 r16 em32 em16)
				     (lambda (x y) (r-r/m 1 #x8e x y)))
				(and um32 (lambda (x y)
					    (if (= 16 (sassy-bits r))
						(r-r/m 2 #x8e x y)
						(r-r/m 4 #x8e x y))))))
		       (and em32 sreg-not-cs (lambda (x y) (r/m-r 4 #x8c x y)))
		       (and em16 sreg-not-cs (lambda (x y) (r/m-r 2 #x8c x y)))
		       (and um32 sreg-not-cs (lambda (x y)
					       (if (= 16 (sassy-bits r))
						   (r/m-r 2 #x8c x y)
						   (r/m-r 4 #x8c x y)))))))
	     (jmp . ,(meta-lambda
		      (or
		       (and (or erel8 (and 'short (or rel32 rel16 rel8)))
			    (lambda (x) (just-i-rel 1 #xeb x)))
		       (and (?* 'near)
			    (or (and erel32 (lambda (x) (just-i-rel 4 #xe9 x)))
				(and erel16 (lambda (x) (just-i-rel 2 #xe9 x)))
				(and urel32
				     (lambda (x)
				       (if (and (urel16 x)
						(= 16 (sassy-bits r)))
					   (just-i-rel 2 #xe9 x)
					   (just-i-rel 4 #xe9 x))))))
		       (and r32 (lambda (x) (r/m 4 #xff x #b100)))
		       (and r16 (lambda (x) (r/m 2 #xff x #b100)))
		       (and em32 (lambda (x) (r/m 4 #xff x #b100)))
		       (and em16 (lambda (x) (r/m 2 #xff x #b100)))
		       (and m32 (lambda (x)
				  (if (= 16 (sassy-bits r))
				      (r/m 2 #xff x #b100)
				      (r/m 4 #xff x #b100))))
		       (and i16
			    (or (and ei32 (lambda (x y) (i16-i32 4 #xea y x)))
				(and ei16 (lambda (x y) (i16-i16 2 #xea y x)))
			        (and ui32 (lambda (x y)
					    (if (and (ui16 y)
						     (= 16 (sassy-bits r)))
						(i16-i16 2 #xea y x)
						(i16-i32 4 #xea y x))))))
		       (and 'far
			    (or (and em32 (lambda (x) (just-m 4 #xff x #b101)))
				(and em16 (lambda (x) (just-m 2 #xff x #b101)))
				(and um32 (lambda (x)
					    (if (= 16 (sassy-bits r))
						(just-m 2 #xff x #b101)
						(just-m 4 #xff x #b101)))))))))
	     (call . ,(meta-lambda
		       (or
			(and erel32 (lambda (x) (just-i-rel 4 #xe8 x)))
			(and erel16 (lambda (x) (just-i-rel 2 #xe8 x)))
			(and urel32 (lambda (x) 
				      (if (and (urel16 x)
					       (= 16 (sassy-bits r)))
					  (just-i-rel 2 #xe8 x)
					  (just-i-rel 4 #xe8 x))))
			(and i16
			     (or (and ei32 (lambda (x y) (i16-i32 4 #x9a y x)))
				 (and ei16 (lambda (x y) (i16-i16 2 #x9a y x)))
			         (and ui32 (lambda (x y)
					    (if (and (ui16 y)
						     (= 16 (sassy-bits r)))
						(i16-i16 2 #x9a y x)
						(i16-i32 4 #x9a y x))))))
			(and 'far
			     (or (and em32 (lambda (x) (just-m 4 #xff x #b011)))
				 (and em16 (lambda (x) (just-m 2 #xff x #b011)))
				 (and um32 (lambda (x)
					     (if (= 16 (sassy-bits r))
						 (just-m 2 #xff x #b011)
						 (just-m 4 #xff x #b011))))))
			(and r32 (lambda (x) (r/m 4 #xff x #b010)))
			(and r16 (lambda (x) (r/m 2 #xff x #b010)))
			(and em32 (lambda (x) (r/m 4 #xff x #b010)))
			(and em16 (lambda (x) (r/m 2 #xff x #b010)))
			(and um32 (lambda (x)
				    (if (= 16 (sassy-bits r))
					(r/m 2 #xff x #b010)
					(r/m 4 #xff x #b010)))))))
	     (fadd  . ,(gen-fpmath-1 #b000 #xc0 #xc0))
	     (fsub  . ,(gen-fpmath-1 #b100 #xe0 #xe8))
	     (fsubr . ,(gen-fpmath-1 #b101 #xe8 #xe0))
	     (fmul  . ,(gen-fpmath-1 #b001 #xc8 #xc8))
	     (fdiv  . ,(gen-fpmath-1 #b110 #xf0 #xf8))
	     (fdivr . ,(gen-fpmath-1 #b111 #xf8 #xf0))
	     (fdivrp . ,(gen-fpmath-2 #xf0 #xf1))
	     (fdivp  . ,(gen-fpmath-2 #xf8 #xf9))
	     (fmulp  . ,(gen-fpmath-2 #xc8 #xc9))
	     (fsubp  . ,(gen-fpmath-2 #xe8 #xe9))
	     (fsubrp . ,(gen-fpmath-2 #xe0 #xe1))
	     (faddp  . ,(gen-fpmath-2 #xc0 #xc1))
	     (fimul  . ,(gen-fpmath-3 #b001))
	     (fiadd  . ,(gen-fpmath-3 #b000))
	     (fidiv  . ,(gen-fpmath-3 #b110))
	     (fidivr . ,(gen-fpmath-3 #b111))
	     (fisub  . ,(gen-fpmath-3 #b100))
	     (fisubr . ,(gen-fpmath-3 #b101))
	     (fcmovb   . ,(gen-fcmovcc #xda #xc0))
	     (fcmove   . ,(gen-fcmovcc #xda #xc8))
	     (fcmovbe  . ,(gen-fcmovcc #xda #xd0))
	     (fcmovu   . ,(gen-fcmovcc #xda #xd8))
	     (fcmovnb  . ,(gen-fcmovcc #xdb #xc0))
	     (fcmovne  . ,(gen-fcmovcc #xdb #xc8))
	     (fcmovnbe . ,(gen-fcmovcc #xdb #xd0))
	     (fcmovnu  . ,(gen-fcmovcc #xdb #xd8))
	     (fxch   . ,(gen-fp-reg/non #xd9 #xc8 '(#xd9 #xc9)))
	     (fucom  . ,(gen-fp-reg/non #xdd #xe0 '(#xdd #xe1)))
	     (fucomp . ,(gen-fp-reg/non #xdd #xe8 '(#xdd #xe9)))
	     (fld  . ,(gen-fp-3m/st #b000 #b101 #xd9 #xc0))
	     (fstp . ,(gen-fp-3m/st #b011 #b111 #xdd #xd8))
	     (fst . ,(meta-lambda
		      (or (and em64 (lambda (x) (r/m 1 #xdd x #b010)))
			  (and m32 (lambda (x) (r/m 1 #xd9 x #b010)))
			  (and st  (lambda (x) (just-r2 1 #xdd #xd0 x))))))
	     (fild  . ,(gen-fp-3int #b000 #b101))
	     (fistp . ,(gen-fp-3int #b011 #b111))
	     (fist   . ,(gen-fp-2int #xdf #xdb #b010))
	     (ficom  . ,(gen-fp-2int #xde #xda #b010))
	     (ficomp . ,(gen-fp-2int #xde #xda #b011))
	     (fcom  . ,(gen-fp-com #xd0 #xd1 #b010))
	     (fcomp . ,(gen-fp-com #xd8 #xd9 #b011))
	     (fcomi   . ,(meta-lambda
			  (and 'st0 st (lambda (x)
					 (just-r2 1 #xdb #xf0 x)))))
	     (fcomip  . ,(meta-lambda
			  (and 'st0 st (lambda (x)
					 (just-r2 1 #xdf #xf0 x)))))
	     (fucomi  . ,(meta-lambda
			  (and 'st0 st (lambda (x)
					 (just-r2 1 #xdb #xe8 x)))))
	     (fucomip . ,(meta-lambda
			  (and 'st0 st (lambda (x)
					 (just-r2 1 #xdf #xe8 x)))))
	     (fbld  . ,(meta-lambda
			(and m80 (lambda (x) (r/m 1 #xdf x #b100)))))
	     (fbstp . ,(meta-lambda
			(and m80 (lambda (x) (r/m 1 #xdf x #b110)))))
	     (ffree . ,(meta-lambda
			(and st (lambda (x)
				  (just-r2 1 #xdd #xc0 x)))))
	     (fstcw  . ,(meta-lambda
			 (and m16 (lambda (x)
				    (r/m 1 '(#x9b #xd9) x #b111)))))
	     (fnstcw . ,(meta-lambda
			 (and m16 (lambda (x) (r/m 1 #xd9 x #b111)))))
	     (fldcw  . ,(meta-lambda
			 (and m16 (lambda (x) (r/m 1 #xd9 x #b101)))))
	     (fstenv  . ,(meta-lambda
			  (and (or em16 m32)
			       (lambda (x) (r/m 1 '(#x9b #xd9) x #b110)))))
	     (fnstenv . ,(meta-lambda
			  (and (or em16 m32) (lambda (x)
					      (r/m 1 #xd9 x #b110)))))
	     (fldenv  . ,(meta-lambda
			  (and (or em16 m32) (lambda (x)
					      (r/m 1 #xd9 x #b100)))))
	     (fsave   . ,(meta-lambda
			  (and mem-any
			       (lambda (x) (r/m 1 '(#x9b #xdd) x #b110)))))
	     (fnsave  . ,(meta-lambda
			  (and mem-any (lambda (x) (r/m 1 #xdd x #b110)))))
	     (frstor  . ,(meta-lambda
			  (and mem-any
			       (lambda (x) (r/m 1 #xdd x #b100)))))
	     (fxsave  . ,(meta-lambda
			  (and mem-any
			       (lambda (x) (r/m 1 '(#x0f #xae) x #b000)))))
	     (fxrstor . ,(meta-lambda
			  (and mem-any
			       (lambda (x) (r/m 1 '(#x0f #xae) x #b001)))))
	     (fstsw   . ,(meta-lambda
			  (or (and 'ax (begin (just-c 1 '(#x9b #xdf #xe0))))
			      (and m16 (lambda (x)
					 (r/m 1 '(#x9b #xdd) x #b111))))))
	     (fnstsw  . ,(meta-lambda
			  (or (and 'ax (begin (just-c 1 '(#xdf #xe0))))
			      (and m16 (lambda (x) (r/m 1 '#xdd x #b111))))))
	     (movd . ,(meta-lambda
		       (or (and mm (or r32 m32)
				(lambda (x y) (r-r/m 1 '(#x0f #x6e) x y)))
			   (and xmm (or r32 m32)
				(lambda (x y) (r-r/m 1 '(#x66 #x0f #x6e) x y)))
			   (and
			    (or r32 m32) (or (and mm
						  (lambda (x y)
						    (r/m-r 1 '(#x0f #x7e) x y)))
					     (and xmm
						  (lambda (x y)
						    (r/m-r 1 '(#x66 #x0f #x7e)
							   x y))))))))
	     (movq . ,(meta-lambda
		       (or (and mm (or mm m64)
				(lambda (x y) (r-r/m 1 '(#x0f #x6f) x y)))
			   (and xmm (or xmm m64)
				(lambda (x y)
				  (r-r/m 1 '(#xf3 #x0f #x7e) x y)))
			   (and m64 (or (and mm (lambda (x y)
						  (r/m-r 1 '(#x0f #x7f) x y)))
					(and xmm
					     (lambda (x y)
					       (r/m-r 1 '(#x66 #x0f #xd6)
						      x y))))))))
	     (pand      . ,(gen-mmx-log #xdb))
	     (pandn     . ,(gen-mmx-log #xdf))
	     (por       . ,(gen-mmx-log #xeb))
	     (pxor      . ,(gen-mmx-log #xef))
	     (packsswb  . ,(gen-mmx-log #x63))
	     (packssdw  . ,(gen-mmx-log #x6b))
	     (packuswb  . ,(gen-mmx-log #x67))
	     (punpckhbw . ,(gen-mmx-log #x68))
	     (punpckhwd . ,(gen-mmx-log #x69))
	     (punpckhdq . ,(gen-mmx-log #x6a))
	     (paddb     . ,(gen-mmx-log #xfc))
	     (paddw     . ,(gen-mmx-log #xfd))
	     (paddd     . ,(gen-mmx-log #xfe))
	     (paddsb    . ,(gen-mmx-log #xec))
	     (paddsw    . ,(gen-mmx-log #xed))
	     (paddusb   . ,(gen-mmx-log #xdc))
	     (paddusw   . ,(gen-mmx-log #xdd))
	     (psubb     . ,(gen-mmx-log #xf8))
	     (psubw     . ,(gen-mmx-log #xf9))
	     (psubd     . ,(gen-mmx-log #xfa))
	     (psubsb    . ,(gen-mmx-log #xe8))
	     (psubsw    . ,(gen-mmx-log #xe9))
	     (psubusb   . ,(gen-mmx-log #xd8))
	     (psubusw   . ,(gen-mmx-log #xd9))
	     (pmullw    . ,(gen-mmx-log #xd5))
	     (pmulhw    . ,(gen-mmx-log #xe5))
	     (pmaddwd   . ,(gen-mmx-log #xf5))
	     (pcmpeqb   . ,(gen-mmx-log #x74))
	     (pcmpeqw   . ,(gen-mmx-log #x75))
	     (pcmpeqd   . ,(gen-mmx-log #x76))
	     (pcmpgtb   . ,(gen-mmx-log #x64))
	     (pcmpgtw   . ,(gen-mmx-log #x65))
	     (pcmpgtd   . ,(gen-mmx-log #x66))
	     (pavgb     . ,(gen-mmx-log #xe0))
	     (pavgw     . ,(gen-mmx-log #xe3))
	     (pmaxub    . ,(gen-mmx-log #xde))
	     (pmaxsw    . ,(gen-mmx-log #xee))
	     (pminub    . ,(gen-mmx-log #xda))
	     (pminsw    . ,(gen-mmx-log #xea))
	     (pmulhuw   . ,(gen-mmx-log #xe4))
	     (psadbw    . ,(gen-mmx-log #xf6))
	     (punpcklbw . ,(gen-mmx-unplow #x60))
	     (punpcklwd . ,(gen-mmx-unplow #x61))
	     (punpckldq . ,(gen-mmx-unplow #x62))
	     (psrlw . ,(gen-mmx-shr #xd1 #x71 #b010))
	     (psrld . ,(gen-mmx-shr #xd2 #x72 #b010))
	     (psrlq . ,(gen-mmx-shr #xd3 #x73 #b010))
	     (psllw . ,(gen-mmx-shr #xf1 #x71 #b110))
	     (pslld . ,(gen-mmx-shr #xf2 #x72 #b110))
	     (psllq . ,(gen-mmx-shr #xf3 #x73 #b110))
	     (psraw . ,(gen-mmx-shr #xe1 #x71 #b100))
	     (psrad . ,(gen-mmx-shr #xe2 #x72 #b100))
	     (movaps . ,(gen-sse1-mov '(#x0f #x28) '(#x0f #x29)))
	     (movups . ,(gen-sse1-mov '(#x0f #x10) '(#x0f #x11)))
	     (addps      . ,(gen-sse-ps/pd '(#x0f #x58)))
	     (subps      . ,(gen-sse-ps/pd '(#x0f #x5c)))
	     (mulps      . ,(gen-sse-ps/pd '(#x0f #x59)))
	     (divps      . ,(gen-sse-ps/pd '(#x0f #x5e)))
	     (rcpps      . ,(gen-sse-ps/pd '(#x0f #x53)))
	     (sqrtps     . ,(gen-sse-ps/pd '(#x0f #x51)))
	     (rsqrtps    . ,(gen-sse-ps/pd '(#x0f #x52)))
	     (maxps      . ,(gen-sse-ps/pd '(#x0f #x5f)))
	     (minps      . ,(gen-sse-ps/pd '(#x0f #x5d)))
	     (andps      . ,(gen-sse-ps/pd '(#x0f #x54)))
	     (andnps     . ,(gen-sse-ps/pd '(#x0f #x55)))
	     (orps       . ,(gen-sse-ps/pd '(#x0f #x56)))
	     (xorps      . ,(gen-sse-ps/pd '(#x0f #x57)))
	     (unpckhps   . ,(gen-sse-ps/pd '(#x0f #x15)))
	     (unpcklps   . ,(gen-sse-ps/pd '(#x0f #x14)))
	     (addpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x58)))
	     (subpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x5c)))
	     (mulpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x59)))
	     (divpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x5e)))
	     (sqrtpd     . ,(gen-sse-ps/pd '(#x66 #x0f #x51)))
	     (maxpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x5f)))
	     (minpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x5d)))
	     (andpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x54)))
	     (andnpd     . ,(gen-sse-ps/pd '(#x66 #x0f #x55)))
	     (orpd       . ,(gen-sse-ps/pd '(#x66 #x0f #x56)))
	     (xorpd      . ,(gen-sse-ps/pd '(#x66 #x0f #x57)))
	     (unpckhpd   . ,(gen-sse-ps/pd '(#x66 #x0f #x15)))
	     (unpcklpd   . ,(gen-sse-ps/pd '(#x66 #x0f #x14)))
	     (cvtpd2dq   . ,(gen-sse-ps/pd '(#xf2 #x0f #xe6)))
	     (cvttpd2dq  . ,(gen-sse-ps/pd '(#x66 #x0f #xe6)))
	     (cvtdq2ps   . ,(gen-sse-ps/pd '(#x0f #x5b)))
	     (cvtps2dq   . ,(gen-sse-ps/pd '(#x66 #x0f #x5b)))
	     (cvttps2dq  . ,(gen-sse-ps/pd '(#xf3 #x0f #x5b)))
	     (cvtpd2ps   . ,(gen-sse-ps/pd '(#x66 #x0f #x5a)))
	     (punpckhqdq . ,(gen-sse-ps/pd '(#x66 #x0f #x6d)))
	     (punpcklqdq . ,(gen-sse-ps/pd '(#x66 #x0f #x6c)))
	     (addsubps   . ,(gen-sse-ps/pd '(#xf2 #x0f #xd0)))
	     (addsubpd   . ,(gen-sse-ps/pd '(#x66 #x0f #xd0)))
	     (haddps     . ,(gen-sse-ps/pd '(#xf2 #x0f #x7c)))
	     (hsubps     . ,(gen-sse-ps/pd '(#xf2 #x0f #x7d)))
	     (haddpd     . ,(gen-sse-ps/pd '(#x66 #x0f #x7c)))
	     (hsubpd     . ,(gen-sse-ps/pd '(#x66 #x0f #x7d)))
	     (movshdup   . ,(gen-sse-ps/pd '(#xf3 #x0f #x16)))
	     (movsldup   . ,(gen-sse-ps/pd '(#xf3 #x0f #x12)))
	     (addss   . ,(gen-sse1-ss '(#xf3 #x0f #x58)))
	     (subss   . ,(gen-sse1-ss '(#xf3 #x0f #x5c)))
	     (mulss   . ,(gen-sse1-ss '(#xf3 #x0f #x59)))
	     (divss   . ,(gen-sse1-ss '(#xf3 #x0f #x5e)))
	     (rcpss   . ,(gen-sse1-ss '(#xf3 #x0f #x53)))
	     (sqrtss  . ,(gen-sse1-ss '(#xf3 #x0f #x51)))
	     (rsqrtss . ,(gen-sse1-ss '(#xf3 #x0f #x52)))
	     (maxss   . ,(gen-sse1-ss '(#xf3 #x0f #x5f)))
	     (minss   . ,(gen-sse1-ss '(#xf3 #x0f #x5d)))
	     (comiss  . ,(gen-sse1-ss '(#x0f #x2f)))
	     (ucomiss . ,(gen-sse1-ss '(#x0f #x2e)))
	     (movhps . ,(gen-sse1-mov2 '(#x0f #x16) '(#x0f #x17)))
	     (movlps . ,(gen-sse1-mov2 '(#x0f #x12) '(#x0f #x13)))
	     (movhlps . ,(gen-xmm-r/r '(#x0f #x12)))
	     (movlhps . ,(gen-xmm-r/r '(#x0f #x16)))
	     (cmpss . ,(meta-lambda
			(and xmm (or xmm m32) i8
			     (lambda (x y z)
			       (r-r/m-i 1 '(#xf3 #x0f #xc2) x y z)))))
	     (shufps . ,(gen-sse-cmp '(#x0f #xc6)))
	     (cmpps  . ,(gen-sse-cmp '(#x0f #xc2)))
	     (movmskps . ,(gen-sse-movmsk '(#x0f #x50)))
	     (movss . ,(meta-lambda
			(or (and xmm (or xmm m32)
				 (lambda (x y)
				   (r-r/m 1 '(#xf3 #x0f #x10) x y)))
			    (and m32 xmm
				 (lambda (x y)
				   (r/m-r 1 '(#xf3 #x0f #x11) x y))))))
	     (cvtpi2ps . ,(gen-sse-pi2pds '(#x0f #x2a)))
	     (cvtsi2ss . ,(gen-sse-si2sssd '(#xf3 #x0f #x2a)))
	     (cvtps2pi  . ,(gen-sse1-ps2pi #x2d))
	     (cvttps2pi . ,(gen-sse1-ps2pi #x2c))
	     (cvttss2si . ,(gen-sse1-ss2si #x2c))
	     (cvtss2si  . ,(gen-sse1-ss2si #x2d))
	     (ldmxcsr . ,(gen-rm #xae #b010))
	     (stmxcsr . ,(gen-rm #xae #b011))
	     (pextrw . ,(meta-lambda
			 (and r32
			      (or (and mm i8 (lambda (x y z)
					       (r-r/m-i 1 '(#x0f #xc5) x y z)))
				  (and xmm i8)
				  (lambda (x y z)
				    (r-r/m-i 1 '(#x66 #x0f #xc5) x y z))))))
	     (pinsrw . ,(meta-lambda
			 (or (and mm (or r32 m16) i8
				  (lambda (x y z)
				    (r-r/m-i 1 '(#x0f #xc4) x y z)))
			     (and xmm (or r32 m16) i8
				  (lambda (x y z)
				    (r-r/m-i 1 '(#x66 #x0f #xc4) x y z))))))
	     (pmovmskb . ,(meta-lambda
			   (and r32
				(or (and mm (lambda (x y)
					      (r-r/m 1 '(#x0f #xd7) x y)))
				    (and xmm
					 (lambda (x y)
					   (r-r/m 1 '(#x66 #x0f #xd7) x y)))))))
	     (pshufw . ,(meta-lambda
			 (and mm (or mm m64) i8
			      (lambda (x y z) (r-r/m-i 1 '(#x0f #x70) x y z)))))
	     (maskmovq . ,(meta-lambda
			   (and mm mm
				(lambda (x y) (r-r/m 1 '(#x0f #xf7) x y)))))
	     (movntq . ,(meta-lambda
			 (and m64 mm
			      (lambda (x y) (r/m-r 1 '(#x0f #xe7) x y)))))
	     (movntps . ,(gen-sse-movnt '(#x0f #x2b)))
	     (prefetcht0  . ,(gen-rm8 #x18 #b001))
	     (prefetcht1  . ,(gen-rm8 #x18 #b010))
	     (prefetcht2  . ,(gen-rm8 #x18 #b011))
	     (prefetchnta . ,(gen-rm8 #x18 #b000))
	     (sfence . ,(gen-non 1 '(#x0f #xae #xf8)))
	     (movapd . ,(gen-sse1-mov  '(#x66 #x0f #x28) '(#x66 #x0f #x29)))
	     (movupd . ,(gen-sse1-mov  '(#x66 #x0f #x10) '(#x66 #x0f #x11)))
	     (movdqa . ,(gen-sse1-mov '(#x66 #x0f #x6f) '(#x66 #x0f #x7f)))
	     (movdqu . ,(gen-sse1-mov '(#xf3 #x0f #x6f) '(#xf3 #x0f #x7f)))
	     (movhpd . ,(gen-sse1-mov2 '(#x66 #x0f #x16) '(#x66 #x0f #x17)))
	     (movlpd . ,(gen-sse1-mov2 '(#x66 #x0f #x12) '(#x66 #x0f #x13)))
	     (movmskpd . ,(gen-sse-movmsk '(#x66 #x0f #x50)))
	     (movsd . ,(meta-lambda
			(or (begin (just-c 4 #xa5)) ;string instruction
			    (and xmm (or xmm m64)
				 (lambda (x y)
				   (r-r/m 1 '(#xf2 #x0f #x10) x y)))
			    (and m64 xmm
				 (lambda (x y)
				   (r/m-r 1 '(#xf2 #x0f #x11) x y))))))
	     (addsd   . ,(gen-sse2-sd '(#xf2 #x0f #x58)))
	     (subsd   . ,(gen-sse2-sd '(#xf2 #x0f #x5c)))
	     (mulsd   . ,(gen-sse2-sd '(#xf2 #x0f #x59)))
	     (divsd   . ,(gen-sse2-sd '(#xf2 #x0f #x5e)))
	     (maxsd   . ,(gen-sse2-sd '(#xf2 #x0f #x5f)))
	     (minsd   . ,(gen-sse2-sd '(#xf2 #x0f #x5d)))
	     (sqrtsd  . ,(gen-sse2-sd '(#xf2 #x0f #x51)))
	     (comisd  . ,(gen-sse2-sd '(#x66 #x0f #x2f)))
	     (ucomisd . ,(gen-sse2-sd '(#x66 #x0f #x2e)))
	     (cvtdq2pd  . ,(gen-sse2-sd '(#xf3 #x0f #xe6)))
	     (cvtps2pd  . ,(gen-sse2-sd '(#x0f #x5a)))
	     (cvtsd2ss  . ,(gen-sse2-sd '(#xf2 #x0f #x5a)))
	     (cmppd   . ,(gen-sse-cmp '(#x66 #x0f #xc2)))
	     (shufpd  . ,(gen-sse-cmp '(#x66 #x0f #xc6)))
	     (pshuflw . ,(gen-sse-cmp '(#xf2 #x0f #x70)))
	     (pshufhw . ,(gen-sse-cmp '(#xf3 #x0f #x70)))
	     (pshufd  . ,(gen-sse-cmp '(#x66 #x0f #x70)))
	     (cmpsd . ,(meta-lambda
			(or (begin (just-c 4 #xa7)) ;string version
			    (and xmm (or xmm m64) i8
				 (lambda (x y z)
				   (r-r/m-i 1 '(#xf2 #x0f #xc2) x y z))))))
	     (cvttpd2pi . ,(gen-sse-pd2pi '(#x66 #x0f #x2c)))
	     (cvtpd2pi  . ,(gen-sse-pd2pi '(#x66 #x0f #x2d)))
	     (cvtpi2pd  . ,(gen-sse-pi2pds '(#x66 #x0f #x2a)))
	     (cvtss2sd  . ,(gen-sse1-ss '(#xf3 #x0f #x5a)))
	     (cvtsd2si  . ,(gen-sse2-sd2si '(#xf2 #x0f #x2d)))
	     (cvttsd2si . ,(gen-sse2-sd2si '(#xf2 #x0f #x2c)))
	     (cvtsi2sd  . ,(gen-sse-si2sssd '(#xf2 #x0f #x2a)))
	     (movq2dq . ,(meta-lambda
			  (and xmm mm (lambda (x y)
					(r-r/m 1 '(#xf3 #x0f #xd6) x y)))))
	     (movdq2q . ,(meta-lambda
			  (and mm xmm (lambda (x y)
					(r-r/m 1 '(#xf2 #x0f #xd6) x y)))))
	     (pmuludq . ,(gen-mmx-log #xf4))
	     (paddq   . ,(gen-mmx-log #xd4))
	     (psubq   . ,(gen-mmx-log #xfb))
	     (pslldq . ,(gen-sse2-sr #b111))
	     (psrldq . ,(gen-sse2-sr #b011))
	     (pause . ,(gen-non 1 '(#xf3 #x90)))
	     (lfence . ,(gen-non 1 '(#x0f #xae #xe8)))
	     (mfence . ,(gen-non 1 '(#x0f #xae #xf0)))
	     (clflush . ,(gen-rm8 #xae #b111))
	     (maskmovdqu . ,(gen-xmm-r/r '(#x66 #x0f #xf7)))
	     (movntpd . ,(gen-sse-movnt '(#x66 #x0f #x2b)))
	     (movntdq . ,(gen-sse-movnt '(#x66 #x0f #xe7)))
	     (movnti . ,(meta-lambda
			 (and m32 r32
			      (lambda (x y) (r/m-r 1 '(#x0f #xc3) x y)))))
	     (fisttp . ,(meta-lambda
			 (or (and m32 (lambda (x) (r/m 1 #xdb x #b001)))
			     (and m64 (lambda (x) (r/m 1 #xdd x #b001)))
			     (and m16 (lambda (x) (r/m 1 #xdf x #b001))))))
	     (lddqu . ,(meta-lambda
			(and xmm mem-any
			     (lambda (x y) (r-r/m 1 '(#xf2 #x0f #xf0) x y)))))
	     (movddup . ,(gen-sse2-sd '(#xf2 #x0f #x12)))
	     (monitor . ,(gen-non 1 '(#x0f #x01 #xc8)))
	     (mwait . ,(gen-non 1 '(#x0f #x01 #xc9)))
	     )))))) ;end the-opcodes

  (set! emit-direct  %emit-direct)
  (set! emit-direct2 %emit-direct2)
  (set! opcode?      %opcode?))

